package com.smile.commons.cron;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * XXL-Job Cron表达式生成工具类（简化版）
 */
public class CronExpressionGenerator {

    private static final Map<String, String> WEEKDAY_MAP = new HashMap<>();
    static {
        WEEKDAY_MAP.put("SUN", "1");
        WEEKDAY_MAP.put("MON", "2");
        WEEKDAY_MAP.put("TUE", "3");
        WEEKDAY_MAP.put("WED", "4");
        WEEKDAY_MAP.put("THU", "5");
        WEEKDAY_MAP.put("FRI", "6");
        WEEKDAY_MAP.put("SAT", "7");
    }

    // ================= 公共方法 =================

    /**
     * 生成每日间隔执行的Cron表达式
     * 修改：移除了开始时间和结束时间参数
     */
    public static String generateDailyInterval(int intervalDays,
                                               int hour, int minute) {
        return generateDailyIntervalInternal(intervalDays, hour, minute);
    }

    /**
     * 生成每周执行的Cron表达式
     * 修改：移除了开始时间和结束时间参数
     */
    public static String generateWeeklyInterval(int intervalWeeks,
                                                List<String> daysOfWeek,
                                                int hour, int minute) {
        return generateWeeklyIntervalInternal(intervalWeeks, daysOfWeek, hour, minute);
    }

    /**
     * 生成每月固定日期执行的Cron表达式（带间隔月数）
     * 修改：移除了开始时间参数
     */
    public static String generateMonthlySimple(int intervalMonths,
                                               int dayOfMonth,
                                               int hour, int minute) {
        validateDayOfMonth(dayOfMonth);
        return generateMonthlySimpleInternal(intervalMonths, dayOfMonth, hour, minute);
    }

    /**
     * 生成每月固定日期执行的Cron表达式（每月执行）
     * 修改：移除了开始时间和结束时间参数
     */
    public static String generateMonthlyRange(int dayOfMonth,
                                              int hour, int minute) {
        validateDayOfMonth(dayOfMonth);
        return generateMonthlySimpleInternal(1, dayOfMonth, hour, minute);
    }

    // ================= 内部方法 =================

    /**
     * 生成每日间隔执行的Cron表达式（内部方法）
     * 修改：移除了日期范围参数
     */
    private static String generateDailyIntervalInternal(int intervalDays, int hour, int minute) {
        validateTime(hour, minute);
        return String.format("0 %d %d */%d * ?", minute, hour, intervalDays);
    }

    /**
     * 生成每周执行的Cron表达式（内部方法）
     * 修改：移除了日期范围参数
     */
    private static String generateWeeklyIntervalInternal(int intervalWeeks, List<String> daysOfWeek,
                                                         int hour, int minute) {
        validateTime(hour, minute);
        validateDaysOfWeek(daysOfWeek);

        String dayExpr = daysOfWeek.stream()
                .map(day -> WEEKDAY_MAP.getOrDefault(day.toUpperCase(), day))
                .collect(Collectors.joining(","));

        return String.format("0 %d %d ? * %s/%d", minute, hour, dayExpr, intervalWeeks);
    }

    /**
     * 生成每月固定日期执行的Cron表达式（内部方法）
     */
    private static String generateMonthlySimpleInternal(int intervalMonths, int dayOfMonth, int hour, int minute) {
        validateDayOfMonth(dayOfMonth);
        validateTime(hour, minute);
        return String.format("0 %d %d %d */%d ?", minute, hour, dayOfMonth, intervalMonths);
    }

    // ================= 基本验证方法 =================

    private static void validateDayOfMonth(int day) {
        if (day < 1 || day > 31) {
            throw new IllegalArgumentException("日期必须在 1-31 范围内");
        }
    }

    private static void validateTime(int hour, int minute) {
        if (hour < 0 || hour > 23) {
            throw new IllegalArgumentException("小时必须在 0-23 范围内");
        }
        if (minute < 0 || minute > 59) {
            throw new IllegalArgumentException("分钟必须在 0-59 范围内");
        }
    }

    private static void validateDaysOfWeek(List<String> days) {
        if (days == null || days.isEmpty()) {
            throw new IllegalArgumentException("必须指定至少一个工作日");
        }

        for (String day : days) {
            if (!WEEKDAY_MAP.containsKey(day.toUpperCase())) {
                throw new IllegalArgumentException("无效的工作日: " + day +
                        "。有效的值: " + String.join(", ", WEEKDAY_MAP.keySet()));
            }
        }
    }

    // ================= 使用示例 =================

    public static void main(String[] args) {
        // 示例1：每日任务（每隔3天执行）
        System.out.println("每日间隔: " + generateDailyInterval(3, 6, 30));
        // 输出: 0 30 6 */3 * ?

        // 示例2：每周任务（每隔2周，周一和周五执行）
        System.out.println("每周间隔: " + generateWeeklyInterval(2,
                List.of("MON", "FRI"), 8, 45));
        // 输出: 0 45 8 ? * 2,6/2

        // 示例3：每月固定日期任务（每3个月，在5号执行）
        System.out.println("每月简单: " + generateMonthlySimple(3, 5, 3, 0));
        // 输出: 0 0 3 5 */3 ?

        // 示例4：每月固定日期任务（每月在15号9:30执行）
        System.out.println("每月范围: " + generateMonthlyRange(15, 9, 30));
        // 输出: 0 30 9 15 * ?

        // 示例5：每月固定日期任务（每月在5号8:00执行）
        System.out.println("每月执行: " + generateMonthlyRange(5, 8, 0));
        // 输出: 0 0 8 5 * ?
    }
}